#!/usr/bin/python
import urllib
import simplejson


class BuxferClient():
    '''
    BuxferClient class:\n
    Used to communicate with the Buxfer REST API \n\n
    Input: \n
    user - buxfer username (string) \n
    passwd - buxfer password (string) \n\n
    
    Dependencies:\n
    python-simplejson (http://pypi.python.org/pypi/simplejson/)\n
    All data is returned in json format \n
    
    Owner:\n
    Venkatesh Hodavdekar(mail.dizzy@gmail.com)\n
    Visit http://lucidcontraptions.com for more \n
    For more options visit: https://www.buxfer.com/help.php?topic=API
    '''
    
    def __init__(self, user, passwd):
        data = urllib.urlencode({'userid': user,    'password': passwd})
        self.url = 'https://www.buxfer.com/api/'
        command = 'login.json'
        try:
            response = urllib.urlopen('%s%s?%s' %(self.url,command,data)) 
            json = simplejson.load(response)
            status = json['response']['status']
            token = json['response']['token']
            if status == 'OK':
                #: Contain the token returned by the Buxfer API as a private variable
                self.__token__ = token
                print 'Buxfer REST API: Connection successful!'
            else:
                print status
        except:
            print 'Could not connect to the Buxfer REST API'

    def add_transaction(self, description, amount, participants=[], group='', **options):
        '''
        Add Transaction method:\n
        Used to add a new transaction to your account\n\n
        
        Input:\n
        description - name of the transaction (string)\n
        amount - amount for the transaction (string) \n
        participants - participants involved (list)\n
        group - group involved (string) \n
        
        Extra Options:\n
        You can also provide extra options through a key=value pair.\n
        tags - include tags if any eg: tags='food'/tags='food,rent' (string)\n
        acct - include accounts if needed eg: acct='boa' (string)\n
        date - include date if needed eg: date='2009-01-01' [today's date by default] (string)\n
        status - include statues if needed eg: status='pending' [cleared by default] (string)  \n    
        '''
        command = 'add_transaction.json'
        participants = 'with:%s %s'  %(' '.join(participants),group)
        extra_options = ''
        for key, value in options.items():              
            extra_options = extra_options + ' %s:%s' %(key,value)
        text = '%s %s %s %s' %(description, amount, participants, extra_options)
        data = {'format': 'sms', 'text': text, 'token': self.__token__}
        try:
            json = self.post_request(data, command)
            status = json['response']['status']
            if status  == 'OK':
                print 'Add Transaction: Success!'
            else:
                print 'Add Transaction: ' + status
        except:
            print 'Add Transaction: Failed!'

    def upload_statement(self, accountId, statement, **options):
        '''
        Upload Statement method:\n
        Used to upload a statement to your account\n\n
        
        Input:\n
        accountId - the id of the account where the statement is to be uploaded\n
        statement - the statement in csv format\n
        
        Extra Options:\n
        You can also provide extra options through a key=value pair.\n
        dateFormat - the date format to be used    
        '''
    
        command = 'upload_statement.json'
        data = {'accountId': accountId, 'statement': statement, 'token': self.__token__}
        for key, value in options.items():          
            data[key] = value
        try:
            json = self.post_request(data, command)
            status = json['response']['status']
            if status  == 'OK':
                print 'Upload Transaction: Success!'
            else:
                print status
        except:
            print 'Upload Transaction: Failed!'

    def get_transactions(self, **options):
        '''
        Get transaction list method\n
        Used to get a list of transactions for that user.\n
        
        Output:\n
        Returns the last 25 transactions by default\n
        
        Extra Options:\n
        accountId OR accountName\n
        tagId OR tagName\n
        startDate AND endDate OR month: date can be specified as "10 feb 2008", or "2008-02-10". month can be specified as "feb08", "feb 08", or "feb 2008".\n
        budgetId OR budgetName\n
        contactId OR contactName\n
        groupId OR groupName\n
        '''
        command = 'transactions.json'
        data = {'token': self.__token__}
        for key, value in options.items():              
            data[key] = value
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            total = json['response']['numTransactions']
            transactions = json['response']['transactions']
            if status  == 'OK':
                print 'Get Transactions: Success!'
                return total, transactions
            else:
                print 'Get Transactions: ' + status
        except:
            print 'Get Transactions: Failed!'

    def get_reports(self, **options):
        '''
        Get Reports method\n
        Used reports for that user for that user.\n
        
        Output:\n
        Returns the the chart image as well as the raw JSON data\n
        
        Extra Options:\n
        accountId OR accountName\n
        tagId OR tagName\n
        startDate AND endDate OR month: date can be specified as "10 feb 2008", or "2008-02-10". month can be specified as "feb08", "feb 08", or "feb 2008".\n
        budgetId OR budgetName\n
        contactId OR contactName\n
        groupId OR groupName
        '''
        command = 'reports.json'
        data = {'token': self.__token__}
        for key, value in options.items():              
            data[key] = value
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            image = json['response']['analysis']['imageURL']
            data = json['response']['analysis']['rawData']
            if status  == 'OK':
                print 'Get Reports: Success!'
                return image, data              
            else:
                print 'Get Reports: ' + status
        except:
            print 'Get Reports: Failed!'
            
    def get_loans(self):
        '''
        Get Loans method
        Used to get the loans for that user for that user.
        
        Output:\n
        Returns data in JSON format\n
        
        Extra Options:\n
        accountId OR accountName\n
        tagId OR tagName\n
        startDate AND endDate OR month: date can be specified as "10 feb 2008", or "2008-02-10". month can be specified as "feb08", "feb 08", or "feb 2008".\n
        budgetId OR budgetName\n
        contactId OR contactName\n
        groupId OR groupName
        '''
        command = 'loans.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)            
            status = json['response']['status']
            loans = json['response']['loans']
            if status  == 'OK':
                print 'Get Loans: Success!'
                return loans
            else:
                print 'Get Loans: ' + status
        except:
            print 'Get Loans: Failed!'

    def get_tags(self):
        '''
        Get tags method:\n
        Returns a list of all the tags for that user.
        '''
        command = 'tags.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)            
            status = json['response']['status']
            tags = json['response']['tags']
            if status  == 'OK':
                print 'Get Tags: Success!'
                return tags
            else:
                print 'Get Tags: ' + status
        except:
            print 'Get Tags: Failed!'

    def get_budgets(self):
        '''
        Get budgets method:\n
        Returns a list of all the budgets for that user.
        '''
        command = 'budgets.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            budgets = json['response']['budgets']
            if status  == 'OK':
                print 'Get Budgets: Success!'
                return budgets
            else:
                print 'Get Budgets: ' + status
        except:
            print 'Get Budgets: Failed!'

    def get_reminders(self):
        '''
        Get reminders method:\n
        Returns a list of all the reminders for that user.
        '''
        command = 'reminders.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            reminders = json['response']['reminders']
            if status  == 'OK':
                print 'Get Reminders: Success!'
                return reminders
            else:
                print 'Get Reminders: ' + status
        except:
            print 'Get Reminders:: Failed!'

    def get_groups(self):
        '''
        Get reminders method:\n
        Returns a list of all the reminders for that user.
        '''
        command = 'groups.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            groups = json['response']['groups']
            if status  == 'OK':
                print 'Get Groups: Success!'
                return groups
            else:
                print 'Get Groups: '+ status
        except:
            print 'Get Groups: Failed!'

    def get_contacts(self):
        '''
        Get contacts method:\n
        Returns a list of all the contacts for that user with the balances.
        '''    
        command = 'contacts.json'
        data = {'token': self.__token__}
        try:
            json = self.get_request(data, command)
            status = json['response']['status']
            contacts = json['response']['contacts']
            if status  == 'OK':
                print 'Get Contacts: Success!'
                return contacts
            else:
                print 'Get Contacts: '+ status
        except:
            print 'Get Contacts: Failed!'

    def get_request(self, data, command):
        '''This method is used to send get requests to the Buxfer API'''
        params = urllib.urlencode(data)
        response = urllib.urlopen('%s%s?%s' %(self.url,command,params))
        json = simplejson.load(response)
        return json
        
    def post_request(self,data, command):
        '''This method is used to send post requests to the Buxfer API'''
        params = urllib.urlencode(data)
        response = urllib.urlopen('%s%s' %(self.url,command),params)
        json = simplejson.load(response)
        return json
    